package top.conangao.system.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import top.conangao.common.security.domain.SecurityUser;
import top.conangao.common.security.util.SecurityUtils;
import top.conangao.system.assemble.SysMenuAssemble;
import top.conangao.system.constants.MenuTypeEnum;
import top.conangao.system.constants.SystemConstants;
import top.conangao.system.domain.SysMenu;
import top.conangao.system.domain.SysRoleMenu;
import top.conangao.system.domain.SysUserRole;
import top.conangao.system.domain.vo.SysMenuVO;
import top.conangao.system.mapper.SysMenuMapper;
import top.conangao.system.service.SysMenuService;
import top.conangao.system.service.SysRoleMenuService;
import top.conangao.system.service.SysUserRoleService;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

/**
 * @author Admin
 * @description 针对表【sys_menu(菜单表)】的数据库操作Service实现
 * @createDate 2023-12-15 09:24:54
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu>
        implements SysMenuService {

    private final SysMenuAssemble sysMenuAssemble;
    private final SysUserRoleService sysUserRoleService;
    private final SysRoleMenuService sysRoleMenuService;

    @Override
    public List<SysMenu> list() {
        SecurityUser user = SecurityUtils.currentUser();
        if (user.getSuperadmin()) {
            return lambdaQuery().eq(SysMenu::getType, 0).list();
        } else {
            return super.list();
        }
    }

    @Override
    public List<SysMenuVO> treeList() {
        List<SysMenuVO> res = new ArrayList<>();
        SecurityUser securityUser = SecurityUtils.currentUser();
        List<SysMenu> rootMenuList;
        if (securityUser.getSuperadmin()) {
            rootMenuList =
                    lambdaQuery().eq(SysMenu::getParentId, SystemConstants.MenuRootId).eq(SysMenu::getType,
                            MenuTypeEnum.MENU.ordinal()).orderByAsc(SysMenu::getSort).list();
        } else {
            List<SysUserRole> sysUserRoleList =
                    sysUserRoleService.lambdaQuery().eq(SysUserRole::getUserId, securityUser.getId()).list();
            List<Long> roleIds = Optional.ofNullable(sysUserRoleList)
                                         .orElse(Collections.emptyList())
                                         .stream()
                                         .map(SysUserRole::getRoleId)
                                         .toList();
            if (roleIds.isEmpty()) {
                return res;
            }
            List<SysRoleMenu> sysRoleMenuList =
                    sysRoleMenuService.lambdaQuery().in(SysRoleMenu::getRoleId, roleIds).list();
            List<Long> menuIds = Optional.ofNullable(sysRoleMenuList)
                                         .orElse(Collections.emptyList())
                                         .stream()
                                         .map(SysRoleMenu::getMenuId)
                                         .toList();
            if (menuIds.isEmpty()) {
                return res;
            }
            List<SysMenu> sysMenuList = lambdaQuery().in(SysMenu::getId, menuIds)
                                                     .eq(SysMenu::getType, MenuTypeEnum.MENU.ordinal())
                                                     .orderByAsc(SysMenu::getSort)
                                                     .list();
            if (sysMenuList.isEmpty()) {
                return res;
            }
            rootMenuList =
                    sysMenuList.stream().filter(sysMenu -> sysMenu.getParentId() == SystemConstants.MenuRootId).toList();
        }

        if (!rootMenuList.isEmpty()) {
            for (SysMenu sysMenu : rootMenuList) {
                SysMenuVO sysMenuVO = sysMenuAssemble.do2vo(sysMenu);
                sysMenuVO.setChildren(treeMenus(sysMenu.getId()));
                res.add(sysMenuVO);
            }
        }
        return res;
    }

    public List<SysMenuVO> treeMenus(long root) {
        List<SysMenuVO> res = new ArrayList<>();
        List<SysMenu> subMenusList = lambdaQuery().eq(SysMenu::getParentId, root)
                                                  .eq(SysMenu::getType, MenuTypeEnum.MENU.ordinal())
                                                  .orderByAsc(SysMenu::getSort)
                                                  .list();
        if (!subMenusList.isEmpty()) {
            for (SysMenu sysMenu : subMenusList) {
                SysMenuVO sysMenuVO = sysMenuAssemble.do2vo(sysMenu);
                sysMenuVO.setChildren(treeMenus(sysMenu.getId()));
                res.add(sysMenuVO);
            }
        }
        return res;
    }
}




